
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                               proc.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                                                    Forrest Yu, 2005
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include "type.h"
#include "const.h"
#include "protect.h"
//#include "proto.h"
#include "string.h"
#include "proc.h"
#include "proto.h"
#include "global.h"

int hungryNum = 0;

/*======================================================================*
                              schedule
 *======================================================================*/
PUBLIC void schedule()
{	
	// 轮流调度所有进程，寻找下一个非睡眠进程

	// 找到当前进程（已执行过的）对应的序号
	int n = 0;
	while(n < NR_TASKS){
		if(proc_table + n == p_proc_ready){
			break;
		}
		n ++;
	}
	
	// 找到下一个非睡眠进程
	n = (n+1) % NR_TASKS;
	PROCESS* p = proc_table + n;

	while(1){
		if (p->sleep_ticks == 0){
			p_proc_ready = p;
			break;
		}
		
		n = (n+1) % NR_TASKS;
		p = proc_table + n;
	}

}

/*======================================================================*
                           sys_get_ticks
 *======================================================================*/
PUBLIC int sys_get_ticks()
{
	return ticks;
}

/*======================================================================*
                           sys_print_str
 *======================================================================*/
PUBLIC void sys_print_str(char* str)
{
	disp_str(str);
}

/*======================================================================*
                           sys_print_str_color
 *======================================================================*/
PUBLIC void sys_print_str_color(char* str, int color)
{
	disp_color_str(str, color);
}

/*======================================================================*
                           sys_sleep
 *======================================================================*/
PUBLIC void sys_sleep(int milli_seconds)
{
	p_proc_ready->sleep_ticks = milli_seconds * HZ / 1000;//设置睡眠时间
	
	schedule();
	p_proc_ready->ticks++;

}

/*======================================================================*
                           sys_time_delay
 *======================================================================*/
PUBLIC void sys_time_delay(int milli_sec)
{
        int t = get_ticks();

        while(((get_ticks() - t) * 1000 / HZ) < milli_sec) {}
}

/*======================================================================*
                           sys_p_operation
 *======================================================================*/
PUBLIC void sys_p_operation(SEMAPHORE* mutex)
{
	mutex->s_num--;

	if(mutex->s_num < 0){
		
		mutex->waitQue[mutex->lenOfWaitQue] = p_proc_ready;//将当前进程加入等待队列
		mutex->lenOfWaitQue++; // 延长等待队列
		sleep((timeUnit * 1000 / HZ) * 256); // 通过冬眠让当前进程进入等待状态
	}
}

/*======================================================================*
                           sys_v_operation
 *======================================================================*/
PUBLIC void sys_v_operation(SEMAPHORE* mutex)
{
	mutex->s_num++;
	if(mutex->s_num <= 0){//如果有等待进程，唤醒第一个进程
		PROCESS* p = mutex->waitQue[0];
		p->sleep_ticks=0;
		
		// 等待队列前移
		
		for(int i=1;i<mutex->lenOfWaitQue;i++){
			mutex->waitQue[i-1]=mutex->waitQue[i];
		}
		
		mutex->lenOfWaitQue--;
	}
}

/*======================================================================*
                           getHungryNum()
 *======================================================================*/
PUBLIC int getHungryNum(){
	return hungryNum;
}